<?php

namespace App\Http\Controllers;

use App\Models\SmsLog;
use App\Models\User;
use App\Models\WxloginMember;
use App\Services\ProjectService;
use App\Services\SmsService;
use App\Services\WechatMassageService;
use Carbon\Carbon;
use EasyWeChat\Factory;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Validator;

class AuthController extends BaseController
{
    // /**
    //  * 需要通过jwt鉴权才能通过的控制器访问，要加上这段构造函数.
    //  */
    // public function __construct()
    // {
    //     $this->middleware('auth:api', ['except' => ['login', 'register']]);
    // }

    /**
     * 获取token.
     * 使用username和password鉴权，数据来源默认admin_users表.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function login()
    {
        $credentials = request(['username', 'password']);

        $user = User::where('username', $credentials['username'])->first();

        if (empty($user)) {
            return fail_message('请先注册用户');
        }

        $lockStatus = ProjectService::checkLoginIsLock($credentials);

        if ($lockStatus['state'] == true) {
            return fail($lockStatus, '账号已被锁定', 401209);
        }

        if ($user->status == 0) {
            return fail_message('账号已经禁用');
        }

        if (!$token = auth('api')->attempt($credentials)) {
            ProjectService::recordLoginError($credentials);
            // redis实现ip/账号锁定
            // $redis_password_error_num = Redis::get('password_error_num' . $ip);

            // if ($redis_password_error_num != null) {
            //     if ($redis_password_error_num >= 3) {
            //         // redis 用户的锁定次数
            //         $redis_user_lock_num = Redis::get('user_lock_num' . $credentials['username']);
            //         // 如果没有被锁定过 就0次
            //         $user_lock_num = empty($redis_user_lock_num) ? 0 : $redis_user_lock_num;
            //         $expire = 60;
            //         if ($user_lock_num == 0) {
            //             Redis::set('user_lock' .  $ip, 1);
            //             Redis::expire('user_lock' . $ip, ($expire * 5));
            //             Redis::set('user_lock_num' . $credentials['username'], $user_lock_num + 1);
            //             // Redis::expire('user_lock_num' . $credentials['username'], ($expire * 5));
            //         } else {
            //             // 锁定次数多了叠加
            //             Redis::set('user_lock' . $ip, 1);
            //             Redis::expire('user_lock' . $ip, ($expire * (5 * $user_lock_num)));
            //             Redis::set('user_lock_num' . $credentials['username'], $user_lock_num + 1);
            //             // Redis::expire('user_lock_num' . $credentials['username'], ($expire * (5 * $user_lock_num)));
            //         }
            //         dd($user_lock_num, $redis_password_error_num);
            //         // 账号锁定
            //     } else {
            //         Redis::set('password_error_num' . $ip, $redis_password_error_num + 1, 60);
            //     }
            // } else {
            //     Redis::set('password_error_num' . $ip, 1, 60);
            // }

            return fail([], '账号或密码错误', 422);
        }

        ProjectService::loginSuccess($credentials);
        return success($this->respondWithToken($token));
    }

    /**
     * 返回token结构体.
     *
     * @param string $token
     * @return \Illuminate\Http\JsonResponse
     */
    protected function respondWithToken(string $token)
    {
        return [
            'access_token' => $token,
            'token_type' => 'bearer',
            'expires_in' => auth('api')->factory()->getTTL() * 60
        ];
    }

    /**
     * 获取当前jwt用户信息.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function me()
    {
        $user = auth('api')->user();
        $user->load(['auth']);
        return success($user);
    }

    /**
     * 注销jwt.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout()
    {
        auth('api')->logout();

        return success();
    }

    /**
     * 刷新token.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function refresh()
    {
        return success($this->respondWithToken(auth('api')->refresh()));
    }

    /**
     * 注册
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2023-08-10
     * @return void
     */
    public function register(Request $request)
    {
        $rules = [
            'phone' => ['required', 'mobile'],
            // 'email' => ['email'],
            'code' => ['required'],
            'password' => ['required', 'min:6', 'max:16', 'same:repwd'],
            // 'realname' => ['required'],
            'repwd' => ['required', 'min:6', 'max:16', 'same:password'],
            // 'company' => ['required'],
            // 'platform'  => ['required'],
        ];

        $message = [
            'phone.required' => '请输入手机号',
            'phone.mobile' => '手机号码格式有误',
            // 'email.required' => '请输入邮箱',
            // 'email.email' => '邮箱格式不正确',
            'code.required' => '请输入验证码',
            'password.required' => '请输入密码',
            'password.min' => '密码不能小于 6 位',
            'password.max' => '密码不能大于 16 位',
            'password.same' => '密码与确认密码不一致',
            // 'realname.required' => '请输入姓名',
            'repwd.required' => '请输入确认密码',
            'repwd.min' => '确认密码不能小于 6 位',
            'repwd.max' => '确认密码不能大于 16 位',
            'repwd.same' => '密码与确认密码不一致',
            // 'company.required' => '请输入公司名称',
        ];

        $payload = $request->only('phone', 'code', 'password', 'repwd', 'realname', 'company', 'email');

        // @todo 增加邀请人、项目、团队id 如果不为空 注册成功之后加入团队、可以查看分享的项目
        $validator = Validator::make($payload, $rules, $message);

        // 验证格式
        if ($validator->fails()) {
            return fail_message($validator->errors()->first());
        }

        // 验证手机号码是否注册过
        if (User::checkPhone($payload['phone'])) {
            return fail_message('该手机号已注册');
        }

        // 验证验证码
        $verify_code = SmsLog::check_code($payload['code'], $payload['phone']);

        if (empty($verify_code)) {
            return fail_message('验证码不正确');
        }

        // 创建用户
        $result = User::create([
            'username' => $payload['phone'],
            // 'email' => $payload['email'] ?? '',
            'realname' => $payload['phone'],
            // 'avatar' => env('DEFAULT_AVATAR'),
            'password' => bcrypt($payload['password']),
            // 'new_password' => bcrypt($user_info['password']),
            'phone' => $payload['phone'],
            'ip' => request()->ip(),
            'created_at' => Carbon::now(),
            'status' => 1,
            // 'company_name' => $payload['company'],
        ]);

        if ($result) {
            SmsLog::use_code($payload['code'], $payload['phone']);
            return success_message('创建用户成功');
        } else {
            return fail_message('创建用户失败');
        }
    }



    /**
     * 忘记密码
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2023-08-14
     * @param Request $request
     * @return json
     */
    public function forgetPassword(Request $request)
    {
        $rules = [
            'phone' => ['required', 'mobile'],
            'code' => ['required'],
            'password' => ['required', 'min:6', 'max:16'],
            'confirm_pwd' => ['required', 'min:6', 'max:16'],
        ];

        $message = [
            'phone.required' => '手机号不能为空',
            'phone.mobile' => '手机号码格式有误',
            'password.required' => '密码不能为空',
            'password.min' => '密码不能小于 6 位',
            'password.max' => '密码不能大于 16 位',
            'confirm_pwd.required' => '确认密码不能为空',
            'confirm_pwd.min' => '确认密码不能小于 6 位',
            'confirm_pwd.max' => '确认密码不能大于 16 位',
            'code.required' => '验证码不能为空',
        ];

        $payload = $request->only('phone', 'code', 'password', 'confirm_pwd');

        $validator = Validator::make($payload, $rules, $message);

        // 验证格式
        if ($validator->fails()) {
            return fail_message($validator->errors()->first());
        }

        // 验证手机号码是否注册过
        if (!User::checkPhone($payload['phone'])) {
            return fail_message('该手机号未注册');
        }


        // 验证验证码
        $verify_code = SmsLog::check_code($payload['code'], $payload['phone']);

        if (empty($verify_code)) {
            return fail_message('验证码不正确');
        }

        if (md5($payload['password']) !== md5($payload['confirm_pwd'])) {
            return fail_message('密码不一致');
        }

        $member = User::where(['username' => $payload['phone']])->first();

        $member->password = bcrypt($payload['confirm_pwd']);
        if ($member->save()) {
            SmsLog::use_code($payload['code'], $payload['phone']);
            return success();
        } else {
            return fail_message();
        }
    }

    /**
     * 发送验证码
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2022-03-02
     * @param Request $request
     * @return json
     */
    public function sendCode(Request $request)
    {

        $rules = [
            'phone' => ['required', 'mobile'],
            'type' => ['required'],
        ];

        $message = [
            'phone.required' => '请输入手机号码',
            'phone.mobile' => '手机号码格式有误',
            'type.required' => '缺少参数',
        ];

        $payload = $request->only('phone', 'type');

        $validator = Validator::make($payload, $rules, $message);

        // 验证格式
        if ($validator->fails()) {
            return fail_message($validator->errors()->first());
        }

        if ($payload['type'] == 'REG') {
            if (User::where('username', $payload['phone'])->first()) {
                return fail_message('该手机号已注册！');
            }
        } elseif ($payload['type'] == 'PWD') {
            $info = User::where('username', $payload['phone'])->first();
            if (empty($info)) {
                return fail_message('该手机号未注册');
            }
        }

        // 查询今日发送条数
        $count = SmsLog::whereDate('add_time', Carbon::today())->where(['phone' => $payload['phone']])->count();

        if ($count >= 20) {
            return fail_message('发送次数过多');
        }
        // 发送验证码
        $res = SmsService::sendCode($payload['phone'], mt_rand(111111, 999999), $payload['type']);

        if (isset($res['yuntongxun']['status']) && $res['yuntongxun']['status'] == 'success') {
            return success($res, '发送成功', 200);
        } else {
            return fail_message('发送失败');
        }
    }

    /**
     * 微信pc扫码登录（这个就相当于是回调接口）
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2022-03-17
     * @param Request $request
     * @return json
     */
    public function scanCode(Request $request)
    {
        $rules = [
            'code' => ['required'],
        ];

        $message = [
            'code.required' => 'code不能为空',
        ];

        $payload = $request->input();

        // noticeLog('=== record input data === ' . json_encode($payload));
        $validator = Validator::make($payload, $rules, $message);

        // 验证格式
        if ($validator->fails()) {
            return fail_message($validator->errors()->first());
        }

        if (!empty($payload['code']) && !empty($payload['state'])) {
            noticeLog('=== record code and state === ' . $payload['code'] . ' === ' . $payload['state']);
            $app = new WechatMassageService();
            // 根据code获取微信信息
            $res = $app->access_token($payload['code']);
            noticeLog('=== record wechat info ===' . json_encode($res));
            if (isset($res->access_token)) {
                // 获取微信用户信息
                $wechat_member_info = $app->wxuserinfo($res->access_token, $res->openid);
                // noticeLog('=== record wechat member info ===' . json_encode($wechat_member_info));

                if ($wechat_member_info) {

                    $member_info = WxloginMember::where('unionid', $res->unionid)->whereNull('delete_time')->first();
                    // noticeLog('=== record wechat login member info ===' . json_encode($member_info));

                    if ($member_info) {
                        if (!empty($member_info['user_id'])) {
                            // noticeLog('=== 有注册用户信息 ===');
                            //有注册信息
                            $member_info->openid = $wechat_member_info->openid;
                            $member_info->nickname = $wechat_member_info->nickname;
                            $member_info->sex = $wechat_member_info->sex;
                            $member_info->province = $wechat_member_info->province;
                            $member_info->city = $wechat_member_info->city;
                            $member_info->country = $wechat_member_info->country;
                            $member_info->headimgurl = $wechat_member_info->headimgurl;
                            // $member_info->addtime = time();
                            $member_info->unionid = $wechat_member_info->unionid;
                            $member_info->save();

                            $uinfo = User::where(['id' => $member_info['user_id']])->whereNull('delete_time')->first();
                            // noticeLog('=== record member info ===' . json_encode($uinfo));
                            //上传微信头像
                            if (!empty($uinfo)) {
                                if ($uinfo->avatar == null) {
                                    $uinfo->avatar = $wechat_member_info->headimgurl;
                                }
                                // $uinfo->realname = $wechat_member_info->nickname;
                                // $uinfo->sex = $wechat_member_info->sex;

                                $uinfo->save();
                                $token = Auth::guard('api')->login($uinfo);

                                if ($token) {
                                    // 登录成功
                                    $uinfo = Auth::guard('api')->user();
                                    $uinfo->last_login_time = Carbon::now();
                                    $uinfo->ip = $request->ip();
                                    $uinfo->save();
                                    return success($this->respondWithToken($token));
                                } else {
                                    return fail_message('登录失败');
                                }
                            } else {
                                // 去绑定
                                return success(['open_id' => $wechat_member_info->unionid, 'access_token' => '']);
                            }
                        } else {
                            // noticeLog('=== 没有关联用户 去绑定 ===');
                            // 去绑定
                            return success(['open_id' => $wechat_member_info->unionid, 'access_token' => '']);
                        }
                    } else {
                        // noticeLog('=== 没有注册微信信息 注册微信信息===');

                        $wechat = new WxloginMember();
                        //没有注册信息就去注册
                        $wechat->openid = $wechat_member_info->openid;
                        $wechat->nickname = $wechat_member_info->nickname;
                        $wechat->sex = $wechat_member_info->sex;
                        $wechat->province = $wechat_member_info->province;
                        $wechat->city = $wechat_member_info->city;
                        $wechat->country = $wechat_member_info->country;
                        $wechat->headimgurl = $wechat_member_info->headimgurl;
                        $wechat->unionid = $wechat_member_info->unionid;
                        // $wechat->addtime = time();
                        // $add = model('WxloginMember')->save($data);
                        if ($wechat->save()) {
                            // noticeLog('=== 注册成功微信信息 去绑定 ===');

                            return success(['open_id' => $wechat_member_info->unionid, 'access_token' => '']);
                        }
                    }
                }
            } else {
                noticeLog('=== No wechat information was obtained ===');
                return fail_message('微信扫码出现一些小故障，请用账号登录~');
            }
        }
    }


    /**
     * 移动端登录
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2024-12-09
     * @param Request $request
     * @return void
     */
    public function mobileLogin(Request $request)
    {

        $rules = [
            'code' => ['required'],
        ];

        $message = [
            'code.required' => 'code不能为空',
        ];

        $payload = $request->input();

        // noticeLog('=== record input data === ' . json_encode($payload));
        $validator = Validator::make($payload, $rules, $message);

        // 验证格式
        if ($validator->fails()) {
            return fail_message($validator->errors()->first());
        }

        $config = [
            'app_id' => 'wx34a084fac740b3d0',
            'secret' => '36a0caafc2d8a54662876ceee067a3f7',
            'response_type' => 'array',
        ];

        $app = Factory::officialAccount($config);

        $oauth = $app->oauth;
        noticeLog('mobile 网页授权开始' . json_encode($oauth));
        $user = $oauth->userFromCode($payload['code']);
        noticeLog('记录根据 code 获取用户信息：' . json_encode($user));
        noticeLog('记录原始API返回的结果：' . json_encode($user->getRaw()));
        $wx_user = $user->getRaw();
        if ($wx_user) {
            // noticeLog('记录用户的uniond ID object : ' . json_encode($wx_user->unionid));
            noticeLog('记录用户的uniond ID array : ' . json_encode($wx_user['unionid']));
            $wx_user_info = WxloginMember::where('unionid', $wx_user['unionid'])->whereNull('delete_time')->first();
            noticeLog('=== 查数据库获取微信用户信息 ===' . json_encode($wx_user_info));

            if ($wx_user_info) {
                if (!empty($wx_user_info['user_id'])) {
                    // noticeLog('=== 有注册用户信息 ===');
                    //有注册信息
                    $wx_user_info->openid = $wx_user['openid'];
                    $wx_user_info->nickname = $wx_user['nickname'];
                    $wx_user_info->sex = $wx_user['sex'];
                    $wx_user_info->province = $wx_user['province'];
                    $wx_user_info->city = $wx_user['city'];
                    $wx_user_info->country = $wx_user['country'];
                    $wx_user_info->headimgurl = $wx_user['headimgurl'];
                    // $member_info->addtime = time();
                    $wx_user_info->unionid = $wx_user['unionid'];
                    $wx_user_info->save();

                    $uinfo = User::where(['id' => $wx_user_info['user_id']])->first();
                    noticeLog('=== 查数据库获取user表用户信息 ===' . json_encode($uinfo));
                    //上传微信头像
                    if (!empty($uinfo)) {
                        if ($uinfo->avatar == null) {
                            $uinfo->avatar = $wx_user['headimgurl'];
                        }
                        // $uinfo->realname = $wechat_member_info->nickname;
                        // $uinfo->sex = $wechat_member_info->sex;

                        $uinfo->save();
                        $token = Auth::guard('api')->login($uinfo);

                        if ($token) {
                            // 登录成功
                            $uinfo = Auth::guard('api')->user();
                            $uinfo->last_login_time = Carbon::now();
                            $uinfo->ip = $request->ip();
                            $uinfo->save();
                            return success($this->respondWithToken($token));
                        } else {
                            return fail_message('登录失败');
                        }
                    } else {
                        // noticeLog('=== 没有关联用户 去绑定 ===');
                        // 去绑定
                        return success(['open_id' => $wx_user['unionid'], 'access_token' => '']);
                    }
                } else {
                    // noticeLog('=== 没有关联用户 去绑定 ===');
                    // 去绑定
                    return success(['open_id' => $wx_user['unionid'], 'access_token' => '']);
                }
            } else {
                // noticeLog('=== 没有注册微信信息 注册微信信息===');

                $wechat = new WxloginMember();
                //没有注册信息就去注册
                $wechat->openid = $wx_user['openid'];
                $wechat->nickname = $wx_user['nickname'];
                $wechat->sex = $wx_user['sex'];
                $wechat->province = $wx_user['province'];
                $wechat->city = $wx_user['city'];
                $wechat->country = $wx_user['country'];
                $wechat->headimgurl = $wx_user['headimgurl'];
                $wechat->unionid = $wx_user['unionid'];

                if ($wechat->save()) {
                    // noticeLog('=== 注册成功微信信息 去绑定 ===');

                    return success(['open_id' => $wx_user['unionid'], 'access_token' => '']);
                }
            }
        }
    }



    /**
     * 绑定手机号码
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2022-03-17
     * @param Request $request
     * @return json
     */
    public function bindPhone(Request $request)
    {
        $rules = [
            'phone' => ['required'],
            'code' => ['required'],
            'open_id' => ['required'],
            // 'company_name' => ['required'],
        ];

        $message = [
            'phone.required' => '手机号码不能为空',
            'code.required' => '验证码不能为空',
            'open_id.required' => 'open_id不能为空',
            // 'company_name.required' => '请输入公司名称'
        ];

        $payload = $request->input();
        $validator = Validator::make($payload, $rules, $message);

        // 验证格式
        if ($validator->fails()) {
            return fail_message($validator->errors()->first());
        }

        // 验证验证码
        $verify_code = SmsLog::check_code($payload['code'], $payload['phone']);


        if (empty($verify_code)) {
            return fail_message('验证码不正确');
        }


        $member_info = User::where('username', $payload['phone'])->first();

        // 如果注册过
        if (!empty($member_info)) {
            //查询手机号是否被冻结
            if ($member_info['status'] == 0) {
                return fail_message('该手机号已被禁用');
            }

            // 查询账号id是否已绑定其他微信，并判断openid是否对应，不对应的话再查询openid
            $wx_info = WxloginMember::where('user_id', $member_info['id'])->whereNull('delete_time')->first();

            if ($wx_info) {
                if ($wx_info['unionid'] != $payload['open_id']) {
                    return fail_message('手机号已绑定其他账号');
                }
            }

            $wx_user_info = WxloginMember::where('unionid', $payload['open_id'])->whereNull('delete_time')->first();
            // noticeLog('=== 微信用户信息 ==='.json_encode($wx_user_info));
            //上传微信头像
            if ($member_info['avatar'] == null || $member_info['avatar'] == 'https://resources.gongshicloud.com/system/avatar.png') {

                $member_info->avatar = $wx_user_info['headimgurl'];
                $member_info->save();
            }

            $wx_user_info->user_id = $member_info['id'];

            if ($wx_user_info->save()) {

                $token = auth('api')->login($member_info);

                SmsLog::use_code($payload['code'], $payload['phone']);
                if ($token) {
                    // 登录成功
                    $member_info = auth('api')->user();
                    $member_info->phone = $payload['phone'];
                    $member_info->last_login_time = Carbon::now();
                    $member_info->ip = $request->ip();
                    $member_info->save();
                    return success($this->respondWithToken($token));
                }
            } else {
                return fail_message("绑定失败");
            }
        } else {
            //如果没有注册过，直接注册
            //检测验证码


            if (!SmsLog::check_code($payload['code'], $payload['phone'])) {
                return fail_message("验证码填写错误");
            }


            $res = User::weRegister($payload);

            if ($res['status'] == 1) {

                $wx_info = WxloginMember::where('unionid', $payload['open_id'])->whereNull('delete_time')->first();
                $wx_info->user_id = $res['id'];
                $wx_info->save();

                $token = Auth::guard('api')->login($res);

                if ($token) {
                    // 登录成功
                    $res = auth('api')->user();
                    $res->last_login_time = Carbon::now();
                    $res->ip = $request->ip();
                    $res->save();
                    return success($this->respondWithToken($token));
                }
            } else {
                return fail_message();
            }
        }
    }
}
